/*-------------------------------------------------------------------------------------------------
  LCD Library (44780 compatible).

  No usa el pin R/W, ya que normalmente se lo conecta a la masa del circuito.
  Fecha de creación: 8/04/2009
  Autor: Felixls
  Web: http://sergiols.blogspot.com

  Changelog:
  Fecha   Versión     Observaciones
  8/4/09  1.00        Versión inicial
  19/05/11 1.01	      Version adaptada para lcd 20 x 4 lineas y funcionando con Xt de 20MHz con PLL a 48MHz
 * 19/04/12 1.02      Version adaptada para lcd 16 x 2 lineas con XT = 4MHz compilador 3.0.0


  Frecuencia de reloj: 48MHZ
  Compilador: SDCC 2.9.1

  Actualizacion: Esta actualizacion es
  19 de mayo de 2011, modifico la libreria para poder usarla con la de hunif
  simple_delay.h
  * Se agregan #define LCD_LINEA 3 y LCD_LINEA_4 para usar una lcd de 4 lineas
  * Se agrega la funcion lcd_gotoxy, adaptada de la version de CCS
  * El encabezado de tu archivo main debe ser el siguiente

  code char at __CONFIG1L CONFIG1L = _PLLDIV_DIVIDE_BY_5__20MHZ_INPUT__1L & _CPUDIV__OSC1_OSC2_SRC___1__96MHZ_PLL_SRC___2__1L & _USBPLL_CLOCK_SRC_FROM_96MHZ_PLL_2_1L;
code char at __CONFIG1H CONFIG1H = _OSC_HS__HS_PLL__USB_HS_1H & _FCMEN_ON_1H & _IESO_ON_1H;
code char at __CONFIG2L CONFIG2L = _PUT_ON_2L & _BODEN_ON_2L & _BODENV_4_2V_2L & _VREGEN_ON_2L;
code char at __CONFIG2H CONFIG2H = _WDT_DISABLED_CONTROLLED_2H & _WDTPS_1_32768_2H;
code char at __CONFIG3H CONFIG3H = _CCP2MUX_RC1_3H & _PBADEN_PORTB_4_0__CONFIGURED_AS_DIGITAL_I_O_ON_RESET_3H & _LPT1OSC_ON_3H & _MCLRE_MCLR_OFF_RE3_ON_3H;
code char at __CONFIG4L CONFIG4L = _STVR_ON_4L & _LVP_OFF_4L & _ENHCPU_OFF_4L & _BACKBUG_OFF_4L;
code char at __CONFIG5L CONFIG5L = _CP_0_OFF_5L & _CP_1_OFF_5L & _CP_2_OFF_5L & _CP_3_OFF_5L;
code char at __CONFIG5H CONFIG5H = _CPB_OFF_5H;
code char at __CONFIG6L CONFIG6L = _WRT_0_OFF_6L & _WRT_1_OFF_6L & _WRT_2_OFF_6L & _WRT_3_OFF_6L;
code char at __CONFIG6H CONFIG6H = _WRTC_OFF_6H & _WRTB_OFF_6H;
code char at __CONFIG7L CONFIG7L = _EBTR_0_OFF_7L & _EBTR_1_OFF_7L & _EBTR_2_OFF_7L & _EBTR_3_OFF_7L;
code char at __CONFIG7H CONFIG7H = _EBTRB_OFF_7H;


  --Autor: Miguel Montiel Martinez
  -------------------------------------------------------------------------------------------------*/



/*  PORTB:4  ----->  LCD bit 4           */
/*  PORTB:5  ----->  LCD bit 5           */
/*  PORTB:6  ----->  LCD bit 6           */
/*  PORTB:7  ----->  LCD bit 7           */
/*  PORTB:2  ----->  LCD RS              */
/*  PORTB:3  ----->  LCD E               */


#define LCD_DATA                PORTB // Puerto de datos
#define LCD_DATA_TRIS           TRISB // Control del puerto de datos
#define LCD_RS                  PORTBbits.RB2   // Modo
#define LCD_ENABLE              PORTBbits.RB3   // Habilitación/deshab. en envíos de datos al lcd.
#define LCD_CLEAR                0x01 // Clear Display
#define LCD_HOME                 0x02 // Cursor a Home
#define LCD_NORMAL               0x06 // Cursor en modo incrementar.
#define LCD_REV                  0x04 // Normal-reverse
#define LCD_SCROLL               0x07 // Usa scroll
#define LCD_SCROLL_REV           0x05 // Reverse
#define LCD_D8_BIT               0x38 // 8 bit 2 lineas ( 5x7 font )
#define LCD_D4_BIT_CONF          0x20 // 4 bit
#define LCD_D4_BIT               0x28 // 4 bit 2 lineas ( 5x7 font )
#define LCD_RESET                0x30 // Reset
#define LCD_DIS_ON               0x0C // Display on modo 2 lineas
#define LCD_DIS_OFF              0x08 // Display off
#define LCD_LINE1                0x80 // Linea 1 posicion 1 1000 0000
#define LCD_LINE2                0xC0 // Linea 2 posicion 1 1010 0000
#define LCD_LINE3		 0x94 //Linea 3 posicion  1
#define LCD_LINE4		 0xD4 //Linea 4 posicion  1
#define LCD_CURSOR_ON            0x0E // Cursor on
#define LCD_CURSOR_OFF           0x0C // Cursor off
#define LCD_BLINK_ON             0x0F // Cursor blink
#define LCD_CURSOR_DER           0x14 // Mover cursor derecha
#define LCD_CURSOR_IZQ           0x10 // Mover cursor izquierda
#define LCD_DISPLAY__DER         0x1C // Scroll display derecha
#define LCD_DISPLAY__IZQ         0x18 // Scroll display izquierda
#define LCD_CHARMODE             0x01
#define LCD_COMMANDMODE          0x00
#define LCD_CGRAM1		 0x40 //primera direccion para CGRAM
#define LCD_CGRAM2		 0x48 //segunda direccion para CGRAM#define FOSC 48000000


#define USE_RW

void lcd_init (void);
void lcd_send( char mode, char dato );
void lcd_message ( char * mess );
void lcd_send_quartet( char mode, char dato );
char lcd_hexa(char a);
void lcd_showint(unsigned int value);
void lcd_showintright(unsigned int value, int index);
void lcd_gotoxy(char x, char y);


void lcd_send_quartet( char mode, char dato )
{
    LCD_RS = mode;
    PORTB = dato  | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
	delay_ms(1);
    LCD_ENABLE = 0;
}



void lcd_send( char mode, char dato )
{
    //unsigned int j;
    char dat = dato;
    LCD_RS = mode;
    dat = dato & 0xf0;
    PORTB = dat | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
	delay_ms(5);
    LCD_ENABLE = 0;
    dat = ((dato<<4)& 0xf0);
    PORTB = dat | (PORTB & 0x0f) ;
    LCD_ENABLE = 1;
	delay_ms(5);
    LCD_ENABLE = 0;
	delay_ms(30);
}





void lcd_init (void)

{
  LCD_DATA_TRIS &= 0x03;
  delay_ms(15);
  lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
  delay_ms(5);
  lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
  delay_ms(1);
  lcd_send_quartet(LCD_COMMANDMODE, LCD_RESET);
  delay_ms(1);
  lcd_send_quartet(LCD_COMMANDMODE, LCD_D4_BIT);
  delay_ms(1);
  lcd_send(LCD_COMMANDMODE, LCD_D4_BIT);
  delay_ms(1);
  lcd_send(LCD_COMMANDMODE, LCD_CLEAR);
  delay_ms(2);
  lcd_send(LCD_COMMANDMODE, LCD_CURSOR_OFF);
  delay_ms(2);
  lcd_send(LCD_COMMANDMODE, LCD_NORMAL);
  delay_ms(1);
  lcd_send(LCD_COMMANDMODE, LCD_DIS_ON);
  delay_ms(1);
}



void lcd_message ( char * mess )

{
  while ( *mess )
  {
    lcd_send(LCD_CHARMODE, *mess ) ;
    mess++ ;
  }
}



char lcd_hexa(char a)
{
    if (a >9)
         a+=55;
    else
        a+=48;
   return a;
}

void lcd_gotoxy(char x, char y)
{
char ADDRESS=0X00;

	switch(y)
	{
	case 1: ADDRESS=LCD_LINE1;
		break;
	case 2: ADDRESS=LCD_LINE2;
		break;
	case 3: ADDRESS=LCD_LINE3;
		break;
	case 4: ADDRESS=LCD_LINE4;
		break;
	default:
		break;
	}

	ADDRESS= (ADDRESS + x) -1;
	lcd_send(LCD_COMMANDMODE,ADDRESS);
}
